import time

from rest_framework.response import Response
from rest_framework.views import APIView

from utils.myjwt import mjwt
from utils.sendmsg import send_message

from .serializers import UserSerializer, ThirdSerializer


class UserListView(APIView):
    def get(self, request):
        users = User.objects.all()
        serializer = UserSerializer(users, many=True)
        return Response(serializer.data)


import re
import random
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from myapp.models import User, ThirdModel
from .serializers import PhoneCodeLoginSerializer, PhonePasswordLoginSerializer
from utils.jwttool import tooljwt
from utils.myredis import redistoll
from django.db import IntegrityError
from .tasks import add, send

import json

# 验证码
class SendCode(APIView):
    def post(self, request):
        phone = request.data.get("phone")
        # if not phone or not isinstance(phone, str):  # 增加非空和类型校验
        #     return Response({"code": 400, "msg": "手机号获取异常，需为字符串"}, status=400)
        # 检查手机号码格式
        if not re.match("^1[3-9]\d{9}$", phone):
            return Response({"code": 400, "msg": "手机号码格式不正确"}, status=status.HTTP_400_BAD_REQUEST)

        code = str(random.randint(1000, 9999))

        rediscode = redistoll.getstr(phone)

        if rediscode:
            return Response({"code": 400, "msg": "发送失败，验证码仍在有效期内"}, status=status.HTTP_400_BAD_REQUEST)
        else:
            try:
                resp = send_message(phone, code)  # 调用第三方发送短信
                resp_data = json.loads(resp)  # 假设返回字符串是 JSON 格式
                if resp_data.get('statusCode') == '000000':
                    redistoll.setstr(phone, code, 60 * 2)
                    return Response({"code": 200, "msg": "发送成功"}, status=status.HTTP_200_OK)
                else:
                    return Response({"code": 400, "msg": f"短信发送失败，错误码: {resp_data.get('statusCode')}"},
                                    status=status.HTTP_400_BAD_REQUEST)
            except Exception as e:
                return Response({"code": 400, "msg": f"短信发送出错: {str(e)}"}, status=status.HTTP_400_BAD_REQUEST)
# 验证码登录
class PhoneCodeLoginView(APIView):
    def post(self, request):
        serializer = PhoneCodeLoginSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        phone = serializer.validated_data['phone']
        code = serializer.validated_data['code']

        # 检查手机号码格式
        if not re.match("^1[3-9]\d{9}$", phone):
            return Response({"code": 400, "msg": "手机号码格式不正确"}, status=status.HTTP_400_BAD_REQUEST)

        # 获取 Redis 中存储的验证码
        rediscode = redistoll.getstr(phone)

        # 检查验证码是否正确
        if not rediscode or rediscode != code:
            return Response({"code": 400, "msg": "验证码错误"}, status=status.HTTP_400_BAD_REQUEST)
        try:
            # 尝试获取用户
            user = User.objects.get(phone=phone)
        except User.DoesNotExist:
            # 如果用户不存在，自动注册
            try:
                # 生成一个默认的用户名，例如手机号
                username = phone
                # 生成一个默认的临时密码，可根据需求修改
                password = str(random.randint(100000, 999999))
                user = User.objects.create(phone=phone, username=username, password=password, user_type=1)
            except IntegrityError:
                return Response({"code": 400, "msg": "注册失败，请稍后重试"}, status=status.HTTP_400_BAD_REQUEST)
        # 生成 JWT token
        token = tooljwt.getToken(user.id, user.phone)
        # 删除 Redis 中的验证码
        redistoll.delkey(phone)
        return Response({"code": 200, "msg": "登录成功", "token": token, "user_id": user.id}, status=status.HTTP_200_OK)
# 密码登录
class PhonePasswordLoginView(APIView):
    def post(self, request):
        serializer = PhonePasswordLoginSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        phone = serializer.validated_data['phone']
        password = serializer.validated_data['password']

        # 检查手机号码格式
        if not re.match("^1[3-9]\d{9}$", phone):
            return Response({"code": 400, "msg": "手机号码格式不正确"}, status=status.HTTP_400_BAD_REQUEST)

        try:
            # 尝试获取用户
            user = User.objects.get(phone=phone)
            if user.password != password:
                return Response({"code": 400, "msg": "密码错误"}, status=status.HTTP_400_BAD_REQUEST)
        except User.DoesNotExist:
            # 如果用户不存在，自动注册
            try:
                # 生成一个默认的用户名，例如手机号
                username = phone
                user = User.objects.create(phone=phone, username=username, password=password, user_type=1)
            except IntegrityError:
                return Response({"code": 400, "msg": "注册失败，请稍后重试"}, status=status.HTTP_400_BAD_REQUEST)

        # 生成 JWT token
        token = tooljwt.getToken(user.id, user.phone)

        return Response({"code": 200, "msg": "登录成功", "token": token, "user_id": user.id}, status=status.HTTP_200_OK)


# 11
# 钉钉登录
# class DingdingUrl(APIView):
#     def get(self, request):
#         curl = "http://localhost:5173/Login/"
#         client_id = 'dingcd8upnh8qifillpn'
#         url = f"https://login.dingtalk.com/oauth2/auth?redirect_uri={curl}&response_type=code&client_id={client_id}&scope=openid corpid&state=dddd&prompt=consent"
#         return Response({'code': 200, 'url': url})
#
# # 回调
# import requests
# class DingdingCallback(APIView):
#     def get(self, request):
#         try:
#             # 获取钉钉回调返回的授权码
#             code = request.query_params.get('code')
#             if not code:
#                 return Response({"error": "授权码缺失"}, status=status.HTTP_400_BAD_REQUEST)
#
#             # 配置你的钉钉开放平台信息
#             client_id = "dingcd8upnh8qifillpn"
#             client_secret = "PyEhCwz6Dlk_IIsw44RuQOfUZ77AQjj6qXPklsPBD0rV9FP_Pb1ArAiT89MhGmGw"
#
#             # 通过授权码换取访问令牌
#             token_url = "https://api.dingtalk.com/v1.0/oauth2/userAccessToken"
#             headers = {
#                 "Content-Type": "application/json"
#             }
#             data = {
#                 "clientId": client_id,
#                 "clientSecret": client_secret,
#                 "code": code,
#                 "grantType": "authorization_code"
#             }
#             token_response = requests.post(token_url, json=data, headers=headers)
#             token_response.raise_for_status()
#             token_data = token_response.json()
#             access_token = token_data.get('accessToken')
#
#             if not access_token:
#                 return Response({"error": "获取访问令牌失败"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
#
#             # 使用访问令牌获取用户信息
#             user_info_url = f"https://api.dingtalk.com/v1.0/contact/users/me?access_token={access_token}"
#             user_info_response = requests.get(user_info_url)
#             user_info_response.raise_for_status()
#             user_info = user_info_response.json()
#
#             # 这里可以添加将用户信息保存到数据库、生成自定义令牌等逻辑
#             # 例如，返回用户信息给前端
#             return Response({"user_info": user_info})
#         except requests.RequestException as e:
#             return Response({"error": f"网络请求错误: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
#         except Exception as e:
#             return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


from rest_framework.views import APIView
from rest_framework.response import Response
import requests
from rest_framework import status


# 第三方登录抽象基类
class ThirdPartyLogin:
    def get_login_url(self):
        pass

    def handle_callback(self, request):
        pass


# 钉钉登录类
class DingdingLogin(ThirdPartyLogin):
    def get_login_url(self):
        curl = "http://localhost:5173/UserCenter/"
        client_id = 'dingcd8upnh8qifillpn'
        url = f"https://login.dingtalk.com/oauth2/auth?redirect_uri={curl}&response_type=code&client_id={client_id}&scope=openid corpid&state=dddd&prompt=consent"
        return url

    def handle_callback(self, request):
        try:
            # 获取钉钉回调返回的授权码
            code = request.query_params.get('code')
            if not code:
                return Response({"error": "授权码缺失"}, status=status.HTTP_400_BAD_REQUEST)

            # 配置你的钉钉开放平台信息
            client_id = "dingcd8upnh8qifillpn"
            client_secret = "PyEhCwz6Dlk_IIsw44RuQOfUZ77AQjj6qXPklsPBD0rV9FP_Pb1ArAiT89MhGmGw"

            # 通过授权码换取访问令牌
            token_url = "https://api.dingtalk.com/v1.0/oauth2/userAccessToken"
            headers = {
                "Content-Type": "application/json"
            }
            data = {
                "clientId": client_id,
                "clientSecret": client_secret,
                "code": code,
                "grantType": "authorization_code"
            }
            token_response = requests.post(token_url, json=data, headers=headers)
            token_response.raise_for_status()
            token_data = token_response.json()
            access_token = token_data.get('accessToken')

            if not access_token:
                return Response({"error": "获取访问令牌失败"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

            # 使用访问令牌获取用户信息
            user_info_url = f"https://api.dingtalk.com/v1.0/contact/users/me?access_token={access_token}"
            user_info_response = requests.get(user_info_url)
            user_info_response.raise_for_status()
            user_info = user_info_response.json()

            # 这里可以添加将用户信息保存到数据库、生成自定义令牌等逻辑
            # 例如，返回用户信息给前端
            return Response({"user_info": user_info})
        except requests.RequestException as e:
            return Response({"error": f"网络请求错误: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


# 第三方登录工厂类
class ThirdPartyLoginFactory:
    @staticmethod
    def create_login(platform):
        if platform == 'dingding':
            return DingdingLogin()
        return None


# 生成登录链接的视图
class ThirdPartyLoginUrl(APIView):
    def get(self, request, platform):
        login = ThirdPartyLoginFactory.create_login(platform)
        if login:
            url = login.get_login_url()
            return Response({'code': 200, 'url': url})
        return Response({"error": "不支持的平台"}, status=status.HTTP_400_BAD_REQUEST)


# 处理回调的视图
class ThirdPartyLoginCallback(APIView):
    def get(self, request, platform):
        login = ThirdPartyLoginFactory.create_login(platform)
        if login:
            return login.handle_callback(request)
        return Response({"error": "不支持的平台"}, status=status.HTTP_400_BAD_REQUEST)


from rest_framework.views import APIView
from rest_framework.response import Response
from django.conf import settings
from utils.myqiniutoken import QiniuTokenGenerator  # 假设工具包路径正确，根据实际项目路径调整

from utils.qiniu_tools import qi


class QiniuImageUploadTokenView(APIView):
    def get(self, request):
        try:
            upload_token = qi.qiniu_token()
            return Response({
                'code': 200,
                'message': '获取图片上传 Token 成功',
                'data': {
                    'upload_token': upload_token,
                }
            })
        except Exception as e:
            return Response({
                'code': 500,
                'message': f'获取图片上传 Token 失败：{str(e)}'
            }, status=500)



# 七牛云和百度云

# myapp/views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from rest_framework.views import APIView
import time
import os
from utils.qiniu_tools import qi
from utils.baidu_api import bdapi
from urllib.parse import quote  # 标准库导入，无需额外安装

# myapp/views.py
@method_decorator(csrf_exempt, name='dispatch')
class UploadImage(APIView):
    def post(self, request):
        try:
            # 文件接收与临时存储
            uploaded_file = request.FILES.get('file')
            if not uploaded_file:
                return JsonResponse({'code': 400, 'msg': '未接收到文件'})

            # 生成唯一文件名
            filename = f"{int(time.time())}_{uploaded_file.name}"
            temp_dir = "temp_uploads"
            os.makedirs(temp_dir, exist_ok=True)
            temp_path = os.path.join(temp_dir, filename)

            with open(temp_path, 'wb+') as destination:
                for chunk in uploaded_file.chunks():
                    destination.write(chunk)

            # 七牛云上传
            qiniu_result = qi.upload_file(temp_path, 3600)
            if qiniu_result['code'] != 200:
                return JsonResponse({'code': 500, 'msg': '七牛云上传失败', 'detail': qiniu_result})

            # # 百度身份证识别
            # image_url = qiniu_result['url']
            # ocr_result = bdapi.idcard(image_url)  # 确保调用idcard方法

            # 获取七牛云URL并进行编码
            image_url = qiniu_result['url']
            # encoded_url = quote(image_url, safe='')  # 强制编码所有特殊字符
            print("七牛云原始URL:", image_url)
            # 调用百度OCR接口时使用编码后的URL
            # ocr_result = bdapi.idcard(encoded_url)  # 传入编码后的URL
            ocr_result= bdapi.idcard(image_url)  # 直接使用七牛云返回的原始URL

            print("编码后URL:", ocr_result)
            # 清理临时文件
            os.remove(temp_path)

            # 统一响应格式
            if ocr_result.get('code') == 200:
                return JsonResponse({
                    'code': 200,
                    'data': {
                        'name': ocr_result.get('name', ''),
                        'id_number': ocr_result.get('id_number', '')
                    }
                })
            else:
                return JsonResponse({
                    'code': ocr_result.get('code', 500),
                    'msg': ocr_result.get('msg', '识别失败')
                })

        except Exception as e:
            return JsonResponse({'code': 500, 'msg': '服务器内部错误', 'error': str(e)})






# import requests

# 回调不行

# 回调
# class DingdingCallBack(APIView):
#     def get(self, request):
#         authCode = request.query_params.get('code')
#
#         # 根据authCode获取用户accessToken
#
#         data = {
#             "clientId": "dingcd8upnh8qifillpn",
#             'clientSecret': "PyEhCwz6Dlk_IIsw44RuQOfUZ77AQjj6qXPklsPBD0rV9FP_Pb1ArAiT89MhGmGw",
#             "code": authCode,
#             'grantType': 'authorization_code'
#         }
#         resp = requests.post('https://api.dingtalk.com/v1.0/oauth2/userAccessToken', json=data).json()
#         accessToken = resp.get('accessToken')
#
#         # 根据accessToken获取用户信息
#         headers = {"x-acs-dingtalk-access-token": accessToken}
#         resp = requests.get('https://api.dingtalk.com/v1.0/contact/users/me', headers=headers).json()
#
#         name = resp.get('nick')
#         uid = resp.get('openId')
#         phone = resp.get('mobile')
#
#         print(name)
#         print(uid)
#         print(phone)
#
#         # 登录，写入三方登录表和用户表
#         third = ThirdModel.objects.filter(uid=uid, types=1).first()
#         if not third:
#             # 写入用户表
#             # 手机号用户存在直接绑定,不存在注册新用户
#             user = User.objects.filter(phone=phone).first()
#             if not user:
#                 userinfo = {
#                     "u_name": name,
#                     "phone": phone,
#                 }
#                 user_ser = UserSerializer(data=userinfo)
#                 if user_ser.is_valid():
#                     user_ser.save()
#                     # 写入三方登录表
#                     third_data = {
#                         "types": 1,
#                         "token": accessToken,
#                         "uid": uid,
#                         "user": user.id
#                     }
#                     sfs = ThirdSerializer(data=third_data)
#                     if sfs.is_valid():
#                         sfs.save()
#                     else:
#                         return Response({"code": 400, "message": "失败", "error": sfs.errors})
#                 else:
#                     return Response({"code": 400, "message": "失败", 'error': user_ser.errors})
#             else:
#                 # 写入三方登录表
#                 third_data = {
#                     "types": 1,
#
#                     "token": accessToken,
#                     "uid": uid,
#                     "user": user.id
#                 }
#                 sfs = ThirdSerializer(data=third_data)
#                 if sfs.is_valid():
#                     sfs.save()
#                 else:
#                     return Response({"code": 400, "message": "失败", "error": sfs.errors})
#         else:
#             user = third.user
#             third.token = accessToken
#             third.save()
#         # 生成jwt token并返回前端
#         payload = {"user": user.id, "phone": user.phone, "exp": int(time.time()) + 60 * 60 * 2}
#         token = mjwt.jwt_encode(payload)
#         payload["exp"] = int(time.time() + 60 * 60 * 24 * 2)
#         re_token = mjwt.jwt_encode(payload)
#         return Response({"code": 200, 'token': token, "user": user.id, "re_token": re_token, })

# 钉钉登录好使
# class DingdingUrl(APIView):
#     def get(self,request):
#         from urllib.parse import quote
#         params = [
#             f"redirect_uri={quote('http://localhost:5173/Login/')}",
#             "response_type=code",
#             "client_id=dingcd8upnh8qifillpn",
#             "scope=openid",
#             "prompt=consent"
#         ]
#         url = "https://login.dingtalk.com/oauth2/auth?" + ("&".join(params))
#         return Response({"url": url})
